package net.cyndeline.componentSystem.movement

import net.cyndeline.entitySystem.{ AbstractEventHandlerSystem, Event, EntityRef }
import net.cyndeline.entitySystem.defaultImpl.Aspect
import net.cyndeline.events.movement.MovementEvent
import net.cyndeline.components.world.{ PositionComponent, OnMapComponent }
import net.cyndeline.components.objectProperties.ObstacleComponent
import language.postfixOps
import net.cyndeline.exceptions.MapMissingException
import com.escalatesoft.subcut.inject.BindingModule
import com.escalatesoft.subcut.inject.Injectable
import net.cyndeline.events.gameplay.RetakeActionEvent
import net.cyndeline.events.gameplay.RetakeAction

/**
 * Cancels any movement to a location outside the map boundary.
 */
class MovementOutOfBoundsSystem(implicit val bindingModule: BindingModule)
extends AbstractEventHandlerSystem(
    new Aspect().getAll(classOf[PositionComponent], classOf[OnMapComponent]),
    classOf[MovementEvent])
with Injectable {
  
  override def onEvent(event: Event, entity: EntityRef): Unit = {    
    event match {
      case m: MovementEvent => verifyMovement(m, entity)
      case _ => {}
    }
  }
  
  private def verifyMovement(event: MovementEvent, entity: EntityRef) {
    val mapInfo = entity.getComponent(classOf[OnMapComponent]) get
    val tileGrid = mapInfo.map
    val stop = event.stop
    
    /* Can't move outside the map. */
    if (stop._1 < 0 
        || stop._1 >= tileGrid.width 
        || stop._2 < 0 
        || stop._2 >= tileGrid.height) {
      event.cancel
      val cancelled = injectOptional[RetakeActionEvent] getOrElse { new RetakeAction() }
      entity.send(cancelled)
      return
    }
  }

}